package com.example.mall.user.svc.interfaces;

import com.example.mall.common.model.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author Mickey
 * @since 2022/4/9
 **/
@RestController
@RequestMapping("/user/account")
@AllArgsConstructor
public class UserAccountController {

    private final WebApplicationContext webApplicationContext;


    @GetMapping("/getAllURL")
    public Result<?> getAllURL() {
        ArrayList<Map<String, String>> objects = new ArrayList<>();

        RequestMappingHandlerMapping requestMappingHandlerMapping = webApplicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();

        for (Map.Entry<RequestMappingInfo, HandlerMethod> requestMappingInfoHandlerMethodEntry : handlerMethods.entrySet()) {
            Map<String, String> resultMap = new LinkedHashMap<>();
            RequestMappingInfo requestMappingInfo = requestMappingInfoHandlerMethodEntry.getKey();
            HandlerMethod handlerMethod = requestMappingInfoHandlerMethodEntry.getValue();
            resultMap.put("className", handlerMethod.getMethod().getDeclaringClass().getName());

            Annotation[] annotations = handlerMethod.getBeanType().getAnnotations();

            for (Annotation annotation : annotations) {
                if (annotation instanceof Api) {
                    Api api = (Api) annotation;
                    resultMap.put("classDesc", api.value());
                } else if (annotation instanceof RequestMapping) {
                    RequestMapping requestMapping = (RequestMapping) annotation;
                    if (requestMapping.value().length > 0) {
                        resultMap.put("classURL", requestMapping.value()[0]);
                    }
                }
            }

            resultMap.put("methodName", handlerMethod.getMethod().getName());
            Annotation[] declaredAnnotations = handlerMethod.getMethod().getDeclaredAnnotations();
            for (Annotation declaredAnnotation : declaredAnnotations) {
                if (declaredAnnotation instanceof ApiOperation) {
                    ApiOperation apiOperation = (ApiOperation) declaredAnnotation;
                    String desc = apiOperation.value();
                    resultMap.put("methodDesc", desc);
                }
            }

            PatternsRequestCondition patternsCondition = requestMappingInfo.getPatternsCondition();
            for (String pattern : patternsCondition.getPatterns()) {
                resultMap.put("methodURL", pattern);
            }

            RequestMethodsRequestCondition methodsCondition = requestMappingInfo.getMethodsCondition();
            for (RequestMethod method : methodsCondition.getMethods()) {
                resultMap.put("requestType", method.toString());
            }

            objects.add(resultMap);
        }

        return Result.OK(objects);
    }
}
